#include "rfid_board.h"
#include "rfid_protocol.h"

#if _RFID_FUNCTION_ENABLE_

/**
 * @brief 验证卡类型是否有效
 *
 * @param Type  - 卡类型
 * @return bool - 验证状态（true：有效 false：无效）
 */
static bool RfidVerifyCardTypeIsValid(uint8_t Type);

/**
 * @brief 验证报文有效性
 *
 * @param pDataIn  - 输入报文
 * @param SizeIn   - 报文长度
 * @return uint8_t - 累加计算值
 */
static uint8_t RfidCalculateSumCheck(const uint8_t *pDataIn, uint16_t SizeIn);

/**
 * @brief 计算给定数据的异或校验值
 *
 * @param pDataIn  - 指向数据的指针
 * @param SizeIn   - 数据的长度
 * @return uint8_t - 异或校验值
 */
static uint8_t RfidCalculateXorValue(const uint8_t *pDataIn, uint16_t SizeIn);

/**
 * @brief 验证分类是否有效
 *
 * @param TranslationCategory - 分类
 * @return bool               - 验证状态（true：有效 false：无效）
 */
static bool RfidVerifyTranslationCategoryValidity(uint16_t TranslationCategory);

/**
 * @brief 验证分组是否有效
 *
 * @param Grouping - 分组
 * @return bool    - 验证状态（true：有效 false：无效）
 */
static bool RfidVerifyGroupingValidity(uint32_t Grouping);

/**
 * @brief 验证房间信息有效性
 *
 * @param NumberOfRoom         - 房间数量
 * @param pCardRoomAttributeIn - 房源信息
 * @param GardenEn             - 园区验证标识
 * @param BuildEn              - 楼栋验证标识
 * @param FloorEn              - 楼层验证标识
 * @param RoomEn               - 房间号验证标志
 * @param SubRoomEn            - 子房间号验证标识
 * @return bool                - 验证状态（true：成功 false：失败）
 */
static bool RfidVerifyTheValidityOfRoomInformation(uint8_t NumberOfRoom, CardRoomAttribute_t *pCardRoomAttributeIn, bool GardenEn, bool BuildEn, bool FloorEn, bool RoomEn, bool SubRoomEn);

/**
 * @brief 核实授权时间
 *
 * @param StartTime          - 授权起始时间
 * @param EndTime            - 授权结束时间
 * @param Date               - 授权周期
 * @param pTimePeriodIn      - 时间段
 * @return bool              - 验证状态（true：成功 false：失败）
 */
static bool RfidVerificationOfAuthorisationTime(const uint32_t StartTime, const uint32_t EndTime, const uint8_t Date, CardCycleUnion_t *pTimePeriodIn);

/**
 * @brief 解析校时卡数据
 *
 * @param pCardInfomationIn - 卡数据
 */
static void RfidPraseCalibrationTimeCardData(RfidProtocolFormat_t *pCardInfomationIn);

/**
 * @brief 解析宾客卡数据
 *
 * @param pCardInfomationIn - 卡数据
 */
static void RfidPraseGuestRoomCardData(RfidProtocolFormat_t *pCardInfomationIn);

/**
 * @brief 解析总卡数据
 *
 * @param pCardInfomationIn - 卡数据
 */
static void RfidPraseMasterRoomCardData(RfidProtocolFormat_t *pCardInfomationIn);

/**
 * @brief 解析楼栋卡数据
 *
 * @param pCardInfomationIn - 卡数据
 */
static void RfidPraseBuildingCardData(RfidProtocolFormat_t *pCardInfomationIn);

/**
 * @brief 解析楼层卡数据
 *
 * @param pCardInfomationIn - 卡数据
 */
static void RfidPraseFloorCardData(RfidProtocolFormat_t *pCardInfomationIn);

/**
 * @brief 解析园区卡数据
 *
 * @param pCardInfomationIn - 卡数据
 */
static void RfidPraseParkCardData(RfidProtocolFormat_t *pCardInfomationIn);

/**
 * @brief 解析安装卡数据
 *
 * @param pCardInfomationIn - 卡数据
 */
static void RfidPraseInstallCardData(RfidProtocolFormat_t *pCardInfomationIn);

/**
 * @brief 解析虚拟卡数据
 *
 * @param pCardInfomationIn - 卡数据
 */
static void RfidPraseVirtualCardSerialNumberData(RfidProtocolFormat_t *pCardInfomationIn);

/**
 * @brief 解析恢复出厂卡数据
 *
 * @param pCardInfomationIn - 卡数据
 */
static void RfidPraseClearCardData(RfidProtocolFormat_t *pCardInfomationIn);

/**
 * @brief 解析常开卡数据
 *
 * @param pCardInfomationIn - 卡数据
 */
static void RfidPraseNormalOpenCardData(RfidProtocolFormat_t *pCardInfomationIn);

const OfflineCardPrase_t OfflineCardPrase[] = {
    [RFID_PARK_CARD] = RfidPraseParkCardData,
    [RFID_CLEAR_CARD] = RfidPraseClearCardData,
    [RFID_FLOOR_CARD] = RfidPraseFloorCardData,
    [RFID_INSTALL_CARD] = RfidPraseInstallCardData,
    [RFID_BUILDING_CARD] = RfidPraseBuildingCardData,
    [RFID_GUEST_ROOM_CARD] = RfidPraseGuestRoomCardData,
    [RFID_MASTER_ROOM_CARD] = RfidPraseMasterRoomCardData,
    [RFID_NORMAL_OPEN_CARD] = RfidPraseNormalOpenCardData,
    [RFID_CALIBRATION_TIME_CARD] = RfidPraseCalibrationTimeCardData,
    [RFID_VIRTUAL_CARD_SERIAL_NUMBER] = RfidPraseVirtualCardSerialNumberData,
};

static bool RfidVerifyCardTypeIsValid(uint8_t Type)
{
  switch (Type)
  {
  case RFID_PARK_CARD:
  case RFID_CLEAR_CARD:
  case RFID_FLOOR_CARD:
  case RFID_INSTALL_CARD:
  case RFID_BUILDING_CARD:
  case RFID_GUEST_ROOM_CARD:
  case RFID_NORMAL_OPEN_CARD:
  case RFID_MASTER_ROOM_CARD:
  case RFID_CALIBRATION_TIME_CARD:
  case RFID_VIRTUAL_CARD_SERIAL_NUMBER:
    return true;
  }

  return false;
}

static uint8_t RfidCalculateSumCheck(const uint8_t *pDataIn, uint16_t SizeIn)
{
  uint32_t SumVal = 0;

  for (uint16_t i = 0; i < SizeIn; i++)
  {
    SumVal += pDataIn[i];
  }

  return (uint8_t)(SumVal & 0x000000FF);
}

static uint8_t RfidCalculateXorValue(const uint8_t *pDataIn, uint16_t SizeIn)
{
  uint8_t XorValue = 0;

  for (uint16_t i = 0; i < SizeIn; i++)
  {
    XorValue ^= pDataIn[i];
  }

  return XorValue;
}

static bool RfidVerifyTranslationCategoryValidity(uint16_t TranslationCategory)
{
  uint16_t TranslationCategoryId = RfidGetRoomType();

  if ((TranslationCategoryId != 0) && (TranslationCategoryId & TranslationCategory))
    return true;

  return false;
}

static bool RfidVerifyGroupingValidity(uint32_t Grouping)
{
  uint32_t GroupingId = RfidGetGroupingNumber();

  if ((GroupingId != 0) && (GroupingId & Grouping))
    return true;

  return false;
}

static bool RfidVerifyTheValidityOfRoomInformation(uint8_t NumberOfRoom, CardRoomAttribute_t *pCardRoomAttributeIn, bool GardenEn, bool BuildEn, bool FloorEn, bool RoomEn, bool SubRoomEn)
{
  if (pCardRoomAttributeIn != NULL)
  {
    uint32_t RoomId = RfidGetRoomNumber();
    uint8_t BuildId = RfidGetBuildNumber();
    uint8_t FloorId = RfidGetFloorNumber();
    uint8_t GardenId = RfidGetGardenNumber();
    uint8_t SubroomId = RfidGetChildRommNumber();

    // 验证门锁归属地
    {
      if (SubroomId == 0)
      {
        SubRoomEn = false;

        if (RoomId == 0)
        {
          RoomEn = false;

          if (FloorId == 0)
          {
            FloorEn = false;

            if (BuildId == 0)
            {
              BuildEn = false;

              if (GardenId == 0)
              {
                GardenEn = false;
              }
            }
          }
        }
      }
    }

    // 验证卡片权限
    {
      for (uint8_t DeviceInfo = 0; DeviceInfo < NumberOfRoom; DeviceInfo++)
      {
        if ((pCardRoomAttributeIn[DeviceInfo].GardenId == GardenId) || (GardenEn == false))
        {
          if ((pCardRoomAttributeIn[DeviceInfo].BuildId == BuildId) || (BuildEn == false))
          {
            if ((pCardRoomAttributeIn[DeviceInfo].FloorId == FloorId) || (FloorEn == false))
            {
              if ((pCardRoomAttributeIn[DeviceInfo].RoomId == RoomId) || (RoomEn == false))
              {
                if ((pCardRoomAttributeIn[DeviceInfo].SubroomId == SubroomId) || (SubRoomEn == false) || (pCardRoomAttributeIn[DeviceInfo].SubroomId == 0))
                  return true;
              }
            }
          }
        }
      }
    }
  }

  return false;
}

static bool RfidVerificationOfAuthorisationTime(const uint32_t StartTime, const uint32_t EndTime, const uint8_t Date, CardCycleUnion_t *pTimePeriodIn)
{
  uint8_t Week = 0, Hour = 0, Minute = 0;
  CardCycleUnion_t *pCardCycleUnion = NULL;
  uint32_t StartTimestamp = 0, EndTimestamp = 0, NowTimestamp = 0;
  uint16_t AllowableTimeError = (uint16_t)(RfidGetAllowableTimeError() * 60);

  if (pTimePeriodIn != NULL)
  {
    if (EndTime > StartTime)
    {
      NowTimestamp = RfidGetTimestamp();
      StartTimestamp = (AllowableTimeError < StartTime) ? (StartTime - AllowableTimeError) : StartTime;
      EndTimestamp = ((UINT32_MAX - AllowableTimeError) >= EndTime) ? (EndTime + AllowableTimeError) : EndTime;
      PRINT("[rfid]: now timestamp: %d, start timestamp: %d, end timestamp: %d.\r\n", NowTimestamp, StartTimestamp, EndTimestamp);

      if ((StartTimestamp <= NowTimestamp) || (RfidGetValidationStartTimeEnableFlag() == false))
      {
        if (EndTimestamp >= NowTimestamp)
        {
          RfidGetTheCurrentTime(NULL, NULL, NULL, &Hour, &Minute, NULL, &Week);

          if ((Date == 0) || (Date & (1 << Week)))
          {
            // 验证时间段是否为空
            {
              uint8_t TimePeriod = 0;

              for (TimePeriod = 0; TimePeriod < OFFLINE_CARD_MAX_TIME_SLOTS; TimePeriod++)
              {
                if (pTimePeriodIn[TimePeriod].BasicCycle != 0)
                  break;
              }

              if (TimePeriod >= OFFLINE_CARD_MAX_TIME_SLOTS)
                return true;
            }

            // 验证时间段是否有效
            {
              for (uint8_t i = 0; i < OFFLINE_CARD_MAX_TIME_SLOTS; i++)
              {
                pCardCycleUnion = &pTimePeriodIn[i];
                if (pCardCycleUnion->BasicCycle != 0)
                {
                  NowTimestamp = (Hour * 60) + Minute;
                  EndTimestamp = (pCardCycleUnion->TimeCycle.EndHour * 60) + pCardCycleUnion->TimeCycle.EndMinute;
                  StartTimestamp = (pCardCycleUnion->TimeCycle.StartHour * 60) + pCardCycleUnion->TimeCycle.StartMinute;

                  if (EndTimestamp <= StartTimestamp)
                  {
                    EndTimestamp += 24 * 60;
                  }

                  if (NowTimestamp < StartTimestamp)
                  {
                    NowTimestamp += 24 * 60;
                  }

                  if ((NowTimestamp >= StartTimestamp) && (NowTimestamp < EndTimestamp))
                    return true;
                }
              }
            }
          }
        }
      }
    }
  }

  return false;
}

static void RfidPraseCalibrationTimeCardData(RfidProtocolFormat_t *pCardInfomationIn)
{
  bool SetStatus = false;

  if (pCardInfomationIn != NULL)
  {
    if (RfidSetTimeZone(pCardInfomationIn->Date) == true)
    {
      if (RfidUpdateRealTime(pCardInfomationIn->StartTimestamp) == true)
      {
        SetStatus = true;
        RfidUpdateDeviceParameters();
      }
    }

    RfidPlaySettingStatusAudio(SetStatus);
    OfflineCardOperationStatus_t OperationStatus = (SetStatus == true) ? OFFLINE_CARD_AUTHENTICATION_SUCCESS : OFFLINE_CARD_AUTHECTICATION_ERROR;
    RfidWriteCalibrationCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OperationStatus);
  }
}

static void RfidPraseGuestRoomCardData(RfidProtocolFormat_t *pCardInfomationIn)
{
  if (pCardInfomationIn != NULL)
  {
    if (RfidGetGuestCardEn() == true)
    {
      if (RfidVerificationOfAuthorisationTime(pCardInfomationIn->StartTimestamp, pCardInfomationIn->EndTimestamp, pCardInfomationIn->Date, pCardInfomationIn->Time) == true)
      {
        if ((RfidVerifyGroupingValidity(pCardInfomationIn->Grouping) == true) ||
            (RfidVerifyTranslationCategoryValidity(pCardInfomationIn->TranslationCategory) == true) ||
            (RfidVerifyTheValidityOfRoomInformation(pCardInfomationIn->NumberOfRoom, pCardInfomationIn->RoomId, true, true, true, true, true) == true))
        {
          bool ValidityResult = true;

          if ((pCardInfomationIn->StartTimestamp >= RfidGetGuestCardReplaceTime()) && (pCardInfomationIn->ReplaceId >= RfidGetGuestCardReplaceId()))
          {
            if (RfidGetAllowedToOpenDoubleLock() != true)
            {
              if (RfidGetDoubleLockEn() == true)
              {
                if (pCardInfomationIn->CardFunction.ControlBit.Recover != true)
                {
                  ValidityResult = false;
                }
              }
            }

            if (ValidityResult == true)
            {
              if ((pCardInfomationIn->CardFunction.ControlBit.Replace == true) || (pCardInfomationIn->ReplaceId > RfidGetGuestCardReplaceId()))
              {
                if (pCardInfomationIn->CardFunction.ControlBit.Replace == true)
                {
                  RfidSetGuestCardReplaceTime(pCardInfomationIn->StartTimestamp);
                }
                else
                {
                  RfidSetGuestCardReplaceId(pCardInfomationIn->ReplaceId);
                }

                RfidUpdateDeviceParameters();
              }

              if (pCardInfomationIn->CardFunction.ControlBit.ClearEn != true)
              {
                RfidWriteGuestCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHENTICATION_SUCCESS);
              }
              else
              {
                RfidWriteClearCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHENTICATION_SUCCESS);
              }

              PRINT("[rfid]: guest room card validation success.\r\n");
              RfidHintAuthenticationSuccessHanlder(RFID_GUEST_ROOM_CARD, pCardInfomationIn->CardSerialNumber, pCardInfomationIn->CardFunction.ControlBit.NormalOpen);
            }
            else
            {
              PRINT("[rfid]: equipment anti-lock.\r\n");

              RfidHintCardOutOfDateHanlder();
              RfidWriteGuestCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
            }
          }
          else
          {
            PRINT("[rfid]: replace time error.\r\n");

            RfidHintCardOutOfDateHanlder();
            RfidWriteGuestCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
          }
        }
        else
        {
          PRINT("[rfid]: failure to verify room information.\r\n");

          RfidHintCardOutOfDateHanlder();
          RfidWriteGuestCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
        }
      }
      else
      {
        PRINT("[rfid]: time verification failed.\r\n");

        RfidHintCardOutOfDateHanlder();
        RfidWriteGuestCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_OUT_OF_DATE);
      }
    }
    else
    {
      PRINT("[rfid]: guest room card is not enabled.\r\n");

      RfidHintCardOutOfDateHanlder();
      RfidWriteGuestCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
    }
  }
}

static void RfidPraseMasterRoomCardData(RfidProtocolFormat_t *pCardInfomationIn)
{
  if (pCardInfomationIn != NULL)
  {
    if (RfidGetMasterCardEn() == true)
    {
      if (RfidVerificationOfAuthorisationTime(pCardInfomationIn->StartTimestamp, pCardInfomationIn->EndTimestamp, pCardInfomationIn->Date, pCardInfomationIn->Time) == true)
      {
        bool ValidityResult = true;

        if ((pCardInfomationIn->StartTimestamp >= RfidGetMasterCardReplaceTime()) && (pCardInfomationIn->ReplaceId >= RfidGetMasterCardReplaceId()))
        {
          if (RfidGetAllowedToOpenDoubleLock() != true)
          {
            if (RfidGetDoubleLockEn() == true)
            {
              if (pCardInfomationIn->CardFunction.ControlBit.Recover != true)
              {
                ValidityResult = false;
              }
            }
          }

          if (ValidityResult == true)
          {
            if ((pCardInfomationIn->CardFunction.ControlBit.Replace == true) || (pCardInfomationIn->ReplaceId > RfidGetMasterCardReplaceId()))
            {
              if (pCardInfomationIn->CardFunction.ControlBit.Replace == true)
              {
                RfidSetMasterCardReplaceTime(pCardInfomationIn->StartTimestamp);
              }
              else
              {
                RfidSetMasterCardReplaceId(pCardInfomationIn->ReplaceId);
              }

              RfidUpdateDeviceParameters();
            }

            if (pCardInfomationIn->CardFunction.ControlBit.ClearEn != true)
            {
              RfidWriteMasterCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHENTICATION_SUCCESS);
            }
            else
            {
              RfidWriteClearCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHENTICATION_SUCCESS);
            }

            PRINT("[rfid]: master room card validation success.\r\n");
            RfidHintAuthenticationSuccessHanlder(RFID_MASTER_ROOM_CARD, pCardInfomationIn->CardSerialNumber, pCardInfomationIn->CardFunction.ControlBit.NormalOpen);
          }
          else
          {
            PRINT("[rfid]: equipment anti-lock.\r\n");

            RfidHintAntiLockHandler();
            RfidWriteMasterCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
          }
        }
        else
        {
          PRINT("[rfid]: replace time error.\r\n");

          RfidHintCardRepaceErrorHandler();
          RfidWriteMasterCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
        }
      }
      else
      {
        PRINT("[rfid]: time verification failed.\r\n");

        RfidHintCardOutOfDateHanlder();
        RfidWriteMasterCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_OUT_OF_DATE);
      }
    }
    else
    {
      PRINT("[rfid]: master room card is not enabled.\r\n");

      RfidHintAuthenticationErrorHanlder();
      RfidWriteMasterCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
    }
  }
}

static void RfidPraseBuildingCardData(RfidProtocolFormat_t *pCardInfomationIn)
{
  if (pCardInfomationIn != NULL)
  {
    if (RfidGetBuildCardEn() == true)
    {
      if (RfidVerificationOfAuthorisationTime(pCardInfomationIn->StartTimestamp, pCardInfomationIn->EndTimestamp, pCardInfomationIn->Date, pCardInfomationIn->Time) == true)
      {
        if ((RfidVerifyGroupingValidity(pCardInfomationIn->Grouping) == true) ||
            (RfidVerifyTranslationCategoryValidity(pCardInfomationIn->TranslationCategory) == true) ||
            (RfidVerifyTheValidityOfRoomInformation(pCardInfomationIn->NumberOfRoom, pCardInfomationIn->RoomId, true, true, false, false, false) == true))
        {
          bool ValidityResult = true;

          if ((pCardInfomationIn->StartTimestamp >= RfidGetBuildCardReplaceTime()) && (pCardInfomationIn->ReplaceId >= RfidGetBuildCardReplaceId()))
          {
            if (RfidGetAllowedToOpenDoubleLock() != true)
            {
              if (RfidGetDoubleLockEn() == true)
              {
                if (pCardInfomationIn->CardFunction.ControlBit.Recover != true)
                {
                  ValidityResult = false;
                }
              }
            }

            if (ValidityResult == true)
            {
              if ((pCardInfomationIn->CardFunction.ControlBit.Replace == true) || (pCardInfomationIn->ReplaceId > RfidGetBuildCardReplaceId()))
              {
                if (pCardInfomationIn->CardFunction.ControlBit.Replace == true)
                {
                  RfidSetBuildCardReplaceTime(pCardInfomationIn->StartTimestamp);
                }
                else
                {
                  RfidSetBuildCardReplaceId(pCardInfomationIn->ReplaceId);
                }

                RfidUpdateDeviceParameters();
              }

              if (pCardInfomationIn->CardFunction.ControlBit.ClearEn != true)
              {
                RfidWriteBuildCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHENTICATION_SUCCESS);
              }
              else
              {
                RfidWriteClearCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHENTICATION_SUCCESS);
              }

              PRINT("[rfid]: master build room card validation success.\r\n");
              RfidHintAuthenticationSuccessHanlder(RFID_BUILDING_CARD, pCardInfomationIn->CardSerialNumber, pCardInfomationIn->CardFunction.ControlBit.NormalOpen);
            }
            else
            {
              PRINT("[rfid]: equipment anti-lock.\r\n");

              RfidHintAntiLockHandler();
              RfidWriteBuildCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
            }
          }
          else
          {
            PRINT("[rfid]: replace time error.\r\n");

            RfidHintCardRepaceErrorHandler();
            RfidWriteBuildCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
          }
        }
        else
        {
          PRINT("[rfid]: failure to verify room information.\r\n");

          RfidHintAuthenticationErrorHanlder();
          RfidWriteBuildCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
        }
      }
      else
      {
        PRINT("[rfid]: time verification failed.\r\n");

        RfidHintCardOutOfDateHanlder();
        RfidWriteBuildCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_OUT_OF_DATE);
      }
    }
    else
    {
      PRINT("[rfid]: master build room card is not enabled.\r\n");

      RfidHintAuthenticationErrorHanlder();
      RfidWriteBuildCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
    }
  }
}

static void RfidPraseFloorCardData(RfidProtocolFormat_t *pCardInfomationIn)
{
  if (pCardInfomationIn != NULL)
  {
    if (RfidGetFloorCardEn() == true)
    {
      if (RfidVerificationOfAuthorisationTime(pCardInfomationIn->StartTimestamp, pCardInfomationIn->EndTimestamp, pCardInfomationIn->Date, pCardInfomationIn->Time) == true)
      {
        if ((RfidVerifyGroupingValidity(pCardInfomationIn->Grouping) == true) ||
            (RfidVerifyTranslationCategoryValidity(pCardInfomationIn->TranslationCategory) == true) ||
            (RfidVerifyTheValidityOfRoomInformation(pCardInfomationIn->NumberOfRoom, pCardInfomationIn->RoomId, true, true, true, false, false) == true))
        {
          bool ValidityResult = true;

          if ((pCardInfomationIn->StartTimestamp >= RfidGetFloorCardReplaceTime()) && (pCardInfomationIn->ReplaceId >= RfidGetFloorCardReplaceId()))
          {
            if (RfidGetAllowedToOpenDoubleLock() != true)
            {
              if (RfidGetDoubleLockEn() == true)
              {
                if (pCardInfomationIn->CardFunction.ControlBit.Recover != true)
                {
                  ValidityResult = false;
                }
              }
            }

            if (ValidityResult == true)
            {
              if ((pCardInfomationIn->CardFunction.ControlBit.Replace == true) || (pCardInfomationIn->ReplaceId > RfidGetFloorCardReplaceId()))
              {
                if (pCardInfomationIn->CardFunction.ControlBit.Replace == true)
                {
                  RfidSetFloorCardReplaceTime(pCardInfomationIn->StartTimestamp);
                }
                else
                {
                  RfidSetFloorCardReplaceId(pCardInfomationIn->ReplaceId);
                }

                RfidUpdateDeviceParameters();
              }

              if (pCardInfomationIn->CardFunction.ControlBit.ClearEn != true)
              {
                RfidWriteFloorCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHENTICATION_SUCCESS);
              }
              else
              {
                RfidWriteClearCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHENTICATION_SUCCESS);
              }

              PRINT("[rfid]: master floor room card validation success.\r\n");
              RfidHintAuthenticationSuccessHanlder(RFID_FLOOR_CARD, pCardInfomationIn->CardSerialNumber, pCardInfomationIn->CardFunction.ControlBit.NormalOpen);
            }
            else
            {
              PRINT("[rfid]: equipment anti-lock.\r\n");

              RfidHintAntiLockHandler();
              RfidWriteFloorCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
            }
          }
          else
          {
            PRINT("[rfid]: replace time error.\r\n");

            RfidHintCardRepaceErrorHandler();
            RfidWriteFloorCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
          }
        }
        else
        {
          PRINT("[rfid]: failure to verify room information.\r\n");

          RfidHintAuthenticationErrorHanlder();
          RfidWriteFloorCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
        }
      }
      else
      {
        PRINT("[rfid]: time verification failed.\r\n");

        RfidHintCardOutOfDateHanlder();
        RfidWriteFloorCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_OUT_OF_DATE);
      }
    }
    else
    {
      PRINT("[rfid]: master floor room card is not enabled.\r\n");

      RfidHintAuthenticationErrorHanlder();
      RfidWriteFloorCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
    }
  }
}

static void RfidPraseParkCardData(RfidProtocolFormat_t *pCardInfomationIn)
{
  if (pCardInfomationIn != NULL)
  {
    if (RfidGetParkCardEn() == true)
    {
      if (RfidVerificationOfAuthorisationTime(pCardInfomationIn->StartTimestamp, pCardInfomationIn->EndTimestamp, pCardInfomationIn->Date, pCardInfomationIn->Time) == true)
      {
        if ((RfidVerifyGroupingValidity(pCardInfomationIn->Grouping) == true) ||
            (RfidVerifyTranslationCategoryValidity(pCardInfomationIn->TranslationCategory) == true) ||
            (RfidVerifyTheValidityOfRoomInformation(pCardInfomationIn->NumberOfRoom, pCardInfomationIn->RoomId, true, false, false, false, false) == true))
        {
          bool ValidityResult = true;

          if ((pCardInfomationIn->StartTimestamp >= RfidGetParkCardReplaceTime()) && (pCardInfomationIn->ReplaceId >= RfidGetParkCardReplaceId()))
          {
            if (RfidGetAllowedToOpenDoubleLock() != true)
            {
              if (RfidGetDoubleLockEn() == true)
              {
                if (pCardInfomationIn->CardFunction.ControlBit.Recover != true)
                {
                  ValidityResult = false;
                }
              }
            }

            if (ValidityResult == true)
            {
              if ((pCardInfomationIn->CardFunction.ControlBit.Replace == true) || (pCardInfomationIn->ReplaceId > RfidGetParkCardReplaceId()))
              {
                if (pCardInfomationIn->CardFunction.ControlBit.Replace == true)
                {
                  RfidSetParkCardReplaceTime(pCardInfomationIn->StartTimestamp);
                }
                else
                {
                  RfidSetParkCardReplaceId(pCardInfomationIn->ReplaceId);
                }

                RfidUpdateDeviceParameters();
              }

              if (pCardInfomationIn->CardFunction.ControlBit.ClearEn != true)
              {
                RfidWriteParkCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHENTICATION_SUCCESS);
              }
              else
              {
                RfidWriteClearCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHENTICATION_SUCCESS);
              }

              PRINT("[rfid]: master park room card validation success.\r\n");
              RfidHintAuthenticationSuccessHanlder(RFID_PARK_CARD, pCardInfomationIn->CardSerialNumber, pCardInfomationIn->CardFunction.ControlBit.NormalOpen);
            }
            else
            {
              PRINT("[rfid]: equipment anti-lock.\r\n");

              RfidHintAntiLockHandler();
              RfidWriteParkCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
            }
          }
          else
          {
            PRINT("[rfid]: replace time error.\r\n");

            RfidHintCardRepaceErrorHandler();
            RfidWriteParkCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
          }
        }
        else
        {
          PRINT("[rfid]: failure to verify room information.\r\n");

          RfidHintAuthenticationErrorHanlder();
          RfidWriteParkCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
        }
      }
      else
      {
        PRINT("[rfid]: time verification failed.\r\n");

        RfidHintCardOutOfDateHanlder();
        RfidWriteParkCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_OUT_OF_DATE);
      }
    }
    else
    {
      PRINT("[rfid]: master park room card is not enabled.\r\n");

      RfidHintAuthenticationErrorHanlder();
      RfidWriteParkCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
    }
  }
}

static void RfidPraseInstallCardData(RfidProtocolFormat_t *pCardInfomationIn)
{
}

static void RfidPraseVirtualCardSerialNumberData(RfidProtocolFormat_t *pCardInfomationIn)
{
  if (pCardInfomationIn != NULL)
  {
    RfidVerifyVirtualCardValidity(pCardInfomationIn->CardSerialNumber);
  }
}

static void RfidPraseClearCardData(RfidProtocolFormat_t *pCardInfomationIn)
{
  bool SetStatus = true;
  uint32_t NumberOfUse = 0;

  if (pCardInfomationIn != NULL)
  {
    NumberOfUse = pCardInfomationIn->StartTimestamp;

    if (NumberOfUse & 0x80000000)
    {
      NumberOfUse &= ~0x80000000;

      if (NumberOfUse == 0)
      {
        SetStatus = false;
      }
    }

    if (SetStatus == true)
    {
      SetStatus = false;

      if (pCardInfomationIn->CardFunction.Ident == 0)
      {
        SetStatus = true;
        RfidStartDeviceFactorySetting();
      }
      else
      {
        if (pCardInfomationIn->CardFunction.ClearBit.ReplaceInfo == true)
        {
          SetStatus = true;

          RfidSetParkCardReplaceId(0);
          RfidSetBuildCardReplaceId(0);
          RfidSetFloorCardReplaceId(0);
          RfidSetGuestCardReplaceId(0);
          RfidSetMasterCardReplaceId(0);
          RfidSetNormalOpenCardReplaceId(0);

          RfidSetParkCardReplaceTime(0);
          RfidSetBuildCardReplaceTime(0);
          RfidSetFloorCardReplaceTime(0);
          RfidSetGuestCardReplaceTime(0);
          RfidSetMasterCardReplaceTime(0);
          RfidSetNormalOpenCardReplaceTime(0);

          RfidUpdateDeviceParameters();
          PRINT("[info]: clear all replace time success.\r\n");
        }

        if (pCardInfomationIn->CardFunction.ClearBit.Cardholder == true)
        {
          SetStatus = true;

          RfidDeleteAllCardholderInformation();
          PRINT("[info]: clear all cardholder success.\r\n");
        }
      }
    }

    if (SetStatus == true)
    {
      RfidWriteClearParameterCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHENTICATION_SUCCESS);
      RfidPlaySettingStatusAudio(SetStatus);
    }
    else
    {
      RfidWriteClearParameterCardNumberLog(pCardInfomationIn->CardSerialNumber, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER, OFFLINE_CARD_AUTHECTICATION_ERROR);
      RfidPlaySettingStatusAudio(SetStatus);
    }
  }
}

static void RfidPraseNormalOpenCardData(RfidProtocolFormat_t *pCardInfomationIn)
{
  if (pCardInfomationIn != NULL)
  {
    if (RfidGetNormalOpenCardEn() == true)
    {
      if (RfidVerificationOfAuthorisationTime(pCardInfomationIn->StartTimestamp, pCardInfomationIn->EndTimestamp, pCardInfomationIn->Date, pCardInfomationIn->Time) == true)
      {
        if ((RfidVerifyGroupingValidity(pCardInfomationIn->Grouping) == true) ||
            (RfidVerifyTranslationCategoryValidity(pCardInfomationIn->TranslationCategory) == true) ||
            ((RfidVerifyTheValidityOfRoomInformation(pCardInfomationIn->NumberOfRoom, pCardInfomationIn->RoomId, true, true, true, true, true) == true) || (pCardInfomationIn->NumberOfRoom == 0)))
        {
          bool ValidityResult = true;

          if ((pCardInfomationIn->StartTimestamp >= RfidGetNormalOpenCardReplaceTime()) && (pCardInfomationIn->ReplaceId >= RfidGetNormalOpenCardReplaceId()))
          {
            if (RfidGetAllowedToOpenDoubleLock() != true)
            {
              if (RfidGetDoubleLockEn() == true)
              {
                if (pCardInfomationIn->CardFunction.ControlBit.Recover != true)
                {
                  ValidityResult = false;
                }
              }
            }

            if (ValidityResult == true)
            {
              if ((pCardInfomationIn->CardFunction.ControlBit.Replace == true) || (pCardInfomationIn->ReplaceId > RfidGetNormalOpenCardReplaceId()))
              {
                if (pCardInfomationIn->CardFunction.ControlBit.Replace == true)
                {
                  RfidSetNormalOpenCardReplaceTime(pCardInfomationIn->StartTimestamp);
                }
                else
                {
                  RfidSetNormalOpenCardReplaceId(pCardInfomationIn->ReplaceId);
                }

                RfidUpdateDeviceParameters();
              }

              bool NormalOpenEn = (RfidDetermineWhetherItIsInTheNormallyOpenState() != true) ? true : false;
              RfidHintAuthenticationSuccessHanlder(RFID_NORMAL_OPEN_CARD, pCardInfomationIn->CardSerialNumber, NormalOpenEn);
            }
            else
            {
              PRINT("[rfid]: equipment anti-lock.\r\n");

              RfidHintAntiLockHandler();
            }
          }
          else
          {
            PRINT("[rfid]: replace time error.\r\n");

            RfidHintCardRepaceErrorHandler();
          }
        }
        else
        {
          PRINT("[rfid]: failure to verify room information.\r\n");

          RfidHintAuthenticationErrorHanlder();
        }
      }
      else
      {
        PRINT("[rfid]: time verification failed.\r\n");

        RfidHintCardOutOfDateHanlder();
      }
    }
    else
    {
      PRINT("[rfid]: master normal open card is not enabled.\r\n");

      RfidHintAuthenticationErrorHanlder();
    }
  }
}

bool RfidValidateCardDataValidity(const uint8_t *pDataIn, const uint8_t *pCardSerialNumberIn, uint8_t CardProtocol)
{
  uint8_t *pDataPacket = (uint8_t *)pDataIn;
  RfidProtocolFormat_t RfidProtocolFormat = {0};

  if ((pDataPacket != NULL) && (pCardSerialNumberIn != NULL))
  {
    memcpy(RfidProtocolFormat.CardSerialNumber, pCardSerialNumberIn, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER);

    // step1: 判断长度是否有效
    {
      RfidProtocolFormat.Length = *pDataPacket++ << 8;
      RfidProtocolFormat.Length |= *pDataPacket++;
      if ((RfidProtocolFormat.Length == 0) || (RfidProtocolFormat.Length > RFID_MAX_LENGTH_OF_OPERATION_DATA))
      {
        PRINT("[rfid]: card length is valid.\r\n");
        return false;
      }
    }

    // step2: 计算 CRC 校验值
    {
      uint8_t CrcCheckValue = 0;

      switch (CardProtocol)
      {
      case RFID_CARD_PROTOCOL_HZ:
        CrcCheckValue = RfidCalculateXorValue(pDataIn, RfidProtocolFormat.Length - 1);
        break;

      default:
        CrcCheckValue = RfidCalculateSumCheck(pDataIn, RfidProtocolFormat.Length - 1);
        break;
      }

      if (CrcCheckValue != pDataIn[RfidProtocolFormat.Length - 1])
      {
        PRINT("[rfid]: abnormal check data, crc value: %02X, agreement: %02X.\r\n", CrcCheckValue, pDataIn[RfidProtocolFormat.Length - 1]);
        return false;
      }
    }

    // step3: 从随机数到校验位前的数据进行AES解密
    {
      uint16_t DecryptDataLength = RfidProtocolFormat.Length - 3;

      if ((DecryptDataLength % 16) != 0)
      {
        PRINT("[rfid]: error in the length of data to be decrypted.\r\n");
        return false;
      }

      // AES 解密
      {
        uint8_t *pDataBuffOffset = pDataPacket;
        uint8_t SectorKeyValue[ENCRYPTION_KEY_LENGTH + 1] = {0};

        // 计算扇区访问密钥
        {
          RfidGetSectorAccessKey(SectorKeyValue);
          switch (CardProtocol)
          {
          case RFID_CARD_PROTOCOL_HZ:
            memcpy(&SectorKeyValue[CRAD_SECTOR_KEY_LENGTH], OFFLINE_CARD_KEY_SUFFIX_HZ, strlen(OFFLINE_CARD_KEY_SUFFIX_HZ));
            break;

          default:
            memcpy(&SectorKeyValue[CRAD_SECTOR_KEY_LENGTH], OFFLINE_CARD_KEY_SUFFIX_YG, strlen(OFFLINE_CARD_KEY_SUFFIX_YG));
            break;
          }
        }

        for (uint8_t i = 0; i < DecryptDataLength / 16; i++)
        {
          RfidAesEcbDecrypt(SectorKeyValue, pDataBuffOffset, pDataBuffOffset);
          pDataBuffOffset += 16;
        }
      }
    }

    // step4: 用随机数对验证码到校验位前的数据进行异或解密
    {
      memcpy(RfidProtocolFormat.Random, pDataPacket, OFFLINE_CARD_RANDOM_BIT_LENGTH);
      pDataPacket += OFFLINE_CARD_RANDOM_BIT_LENGTH;
      RfidCalXorDecrypt(RfidProtocolFormat.Random, OFFLINE_CARD_RANDOM_BIT_LENGTH, pDataPacket, (RfidProtocolFormat.Length - OFFLINE_CARD_RANDOM_BIT_LENGTH - 3));
    }

    // step5: 校验验证码是否正确
    {
      bool CaptchaCheckResult = false;

      memcpy(RfidProtocolFormat.Captcha, pDataPacket, OFFLINE_CARD_CAPTCHA_BIT_LENGTH);
      pDataPacket += OFFLINE_CARD_CAPTCHA_BIT_LENGTH;

      switch (CardProtocol)
      {
      case RFID_CARD_PROTOCOL_HZ:
      {
        if (memcmp(RfidProtocolFormat.Captcha, OFFLINE_CARD_CAPTCHA_DATA_HZ, OFFLINE_CARD_CAPTCHA_BIT_LENGTH) == 0)
        {
          CaptchaCheckResult = true;
        }
      }
      break;

      default:
      {
        if (memcmp(RfidProtocolFormat.Captcha, OFFLINE_CARD_CAPTCHA_DATA_YG, OFFLINE_CARD_CAPTCHA_BIT_LENGTH) == 0)
        {
          CaptchaCheckResult = true;
        }
      }
      break;
      }

      if (CaptchaCheckResult != true)
      {
        PRINT("[rfid]: captcha error.\r\n");
        return false;
      }
    }

    // step6: 判断卡类型是否有效
    {
      RfidProtocolFormat.CardType = *pDataPacket++;
      if (RfidVerifyCardTypeIsValid(RfidProtocolFormat.CardType) != true)
      {
        PRINT("[rfid]: unknown card type.\r\n");
        return false;
      }
    }

    // step7: 获取顶替号
    {
      RfidProtocolFormat.ReplaceId = *pDataPacket++ << 8;
      RfidProtocolFormat.ReplaceId |= *pDataPacket++;
    }

    // step8: 获取类别号
    {
      RfidProtocolFormat.TranslationCategory = *pDataPacket++ << 8;
      RfidProtocolFormat.TranslationCategory |= *pDataPacket++;
    }

    // step9: 获取分组号
    {
      RfidProtocolFormat.Grouping = *pDataPacket++ << 24;
      RfidProtocolFormat.Grouping |= *pDataPacket++ << 16;
      RfidProtocolFormat.Grouping |= *pDataPacket++ << 8;
      RfidProtocolFormat.Grouping |= *pDataPacket++;

      RfidProtocolFormat.Reserved = *pDataPacket++ << 24;
      RfidProtocolFormat.Reserved |= *pDataPacket++ << 16;
      RfidProtocolFormat.Reserved |= *pDataPacket++ << 8;
      RfidProtocolFormat.Reserved |= *pDataPacket++;
    }

    // step10: 获取授权信息
    {
      // 获取授权时间
      {
        RfidProtocolFormat.StartTimestamp = *pDataPacket++ << 24;
        RfidProtocolFormat.StartTimestamp |= *pDataPacket++ << 16;
        RfidProtocolFormat.StartTimestamp |= *pDataPacket++ << 8;
        RfidProtocolFormat.StartTimestamp |= *pDataPacket++;
        RfidProtocolFormat.EndTimestamp = *pDataPacket++ << 24;
        RfidProtocolFormat.EndTimestamp |= *pDataPacket++ << 16;
        RfidProtocolFormat.EndTimestamp |= *pDataPacket++ << 8;
        RfidProtocolFormat.EndTimestamp |= *pDataPacket++;
        RfidProtocolFormat.Date = *pDataPacket++;
      }

      // 获取授权时间段
      {
        uint8_t NumberOfTimeSlots = *pDataPacket++;
        if (NumberOfTimeSlots > OFFLINE_CARD_MAX_TIME_SLOTS)
        {
          PRINT("[rfid]: exceeding time slots limit.\r\n");
          return false;
        }

        for (uint8_t i = 0; i < NumberOfTimeSlots; i++)
        {
          RfidProtocolFormat.Time[i].TimeCycle.StartHour = *pDataPacket++;
          RfidProtocolFormat.Time[i].TimeCycle.StartMinute = *pDataPacket++;
          RfidProtocolFormat.Time[i].TimeCycle.EndHour = *pDataPacket++;
          RfidProtocolFormat.Time[i].TimeCycle.EndMinute = *pDataPacket++;
        }
      }

      // 获取卡片功能
      {
        RfidProtocolFormat.CardFunction.Ident = *pDataPacket++;
      }
    }

    // step11: 获取房间信息
    {
      RfidProtocolFormat.NumberOfRoom = *pDataPacket++;
      if ((RfidProtocolFormat.NumberOfRoom == VIRTUAL_CARD_SERIAL_NUMBER_LENGTH) && (RfidProtocolFormat.CardType == RFID_VIRTUAL_CARD_SERIAL_NUMBER))
      {
        memcpy(RfidProtocolFormat.CardSerialNumber, pDataPacket, VIRTUAL_CARD_SERIAL_NUMBER_LENGTH);
        pDataPacket += VIRTUAL_CARD_SERIAL_NUMBER_LENGTH;
      }
      else
      {
        if (RfidProtocolFormat.NumberOfRoom > OFFLINE_CARD_MAX_ROOM_QUANTITIES)
        {
          PRINT("[rfid]: exceeding room limit.\r\n");
          return false;
        }

        for (uint8_t i = 0; i < RfidProtocolFormat.NumberOfRoom; i++)
        {
          RfidProtocolFormat.RoomId[i].GardenId = *pDataPacket++;
          RfidProtocolFormat.RoomId[i].BuildId = *pDataPacket++;
          RfidProtocolFormat.RoomId[i].FloorId = *pDataPacket++;
          RfidProtocolFormat.RoomId[i].RoomId = *pDataPacket++ << 24;
          RfidProtocolFormat.RoomId[i].RoomId |= *pDataPacket++ << 16;
          RfidProtocolFormat.RoomId[i].RoomId |= *pDataPacket++ << 8;
          RfidProtocolFormat.RoomId[i].RoomId |= *pDataPacket++;
          RfidProtocolFormat.RoomId[i].SubroomId = *pDataPacket++;
        }
      }
    }

    // step12: 执行离线卡相关动作
    {
      if (OfflineCardPrase[RfidProtocolFormat.CardType] != NULL)
      {
        OfflineCardPrase[RfidProtocolFormat.CardType](&RfidProtocolFormat);
      }
    }
  }

  return true;
}

#endif
